home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / dev / gcc / objam01.lha / objam / runtime / encoding.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-10  |  9.9 KB  |  511 lines

  1. /*
  2. ** ObjectiveAmiga: Encoding of types for Objective C
  3. ** See GNU:lib/libobjam/ReadMe for details
  4. */
  5.  
  6.  
  7. #include <ctype.h>
  8.  
  9. #include <libraries/objc.h>
  10. #include <clib/objc_protos.h>
  11.  
  12. #include "misc.h" /* For the ANSI function emulations */
  13.  
  14.  
  15. #define MAX(X, Y)                    \
  16.   ({ typeof(X) __x = (X), __y = (Y); \
  17.      (__x > __y ? __x : __y); })
  18.  
  19. #define MIN(X, Y)                    \
  20.   ({ typeof(X) __x = (X), __y = (Y); \
  21.      (__x < __y ? __x : __y); })
  22.  
  23.  
  24. static inline int
  25. atoi (const char* str)
  26. {
  27.   int res = 0;
  28.   
  29.   while (isdigit (*str))
  30.     res *= 10, res += (*str++ - '0');
  31.  
  32.   return res;
  33. }
  34.  
  35. /*
  36.   return the size of an object specified by type 
  37. */
  38.  
  39. int
  40. objc_sizeof_type(const char* type)
  41. {
  42.   switch(*type) {
  43.   case _C_ID:
  44.     return sizeof(id);
  45.     break;
  46.  
  47.   case _C_CLASS:
  48.     return sizeof(OCClass*);
  49.     break;
  50.  
  51.   case _C_SEL:
  52.     return sizeof(SEL);
  53.     break;
  54.  
  55.   case _C_CHR:
  56.     return sizeof(char);
  57.     break;
  58.     
  59.   case _C_UCHR:
  60.     return sizeof(unsigned char);
  61.     break;
  62.  
  63.   case _C_SHT:
  64.     return sizeof(short);
  65.     break;
  66.  
  67.   case _C_USHT:
  68.     return sizeof(unsigned short);
  69.     break;
  70.  
  71.   case _C_INT:
  72.     return sizeof(int);
  73.     break;
  74.  
  75.   case _C_UINT:
  76.     return sizeof(unsigned int);
  77.     break;
  78.  
  79.   case _C_LNG:
  80.     return sizeof(long);
  81.     break;
  82.  
  83.   case _C_ULNG:
  84.     return sizeof(unsigned long);
  85.     break;
  86.  
  87.   case _C_PTR:
  88.   case _C_ATOM:
  89.   case _C_CHARPTR:
  90.     return sizeof(char*);
  91.     break;
  92.  
  93.   case _C_ARY_B:
  94.     {
  95.       int len = atoi(type+1);
  96.       while (isdigit(*++type));
  97.       return len*objc_aligned_size (type);
  98.     }
  99.     break; 
  100.  
  101.   case _C_STRUCT_B:
  102.     {
  103.       int acc_size = 0;
  104.       int align;
  105.       while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
  106.       while (*type != _C_STRUCT_E);
  107.     {
  108.       align = objc_alignof_type (type);       /* padd to alignment */
  109.       if ((acc_size % align) != 0)
  110.         acc_size += align - (acc_size % align);
  111.       acc_size += objc_sizeof_type (type);   /* add component size */
  112.       type = objc_skip_typespec (type);             /* skip component */
  113.     }
  114.       return acc_size;
  115.     }
  116.  
  117.   case _C_UNION_B:
  118.     {
  119.       int max_size = 0;
  120.       while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
  121.       while (*type != _C_UNION_E)
  122.     {
  123.       max_size = MAX (max_size, objc_sizeof_type (type));
  124.       type = objc_skip_typespec (type);
  125.     }
  126.       return max_size;
  127.     }
  128.     
  129.   default:
  130.     printf("objc_sizeof_type: cannot parse typespec: %s\n", type);
  131.     abort();
  132.   }
  133. }
  134.  
  135.  
  136. /*
  137.   Return the alignment of an object specified by type 
  138. */
  139.  
  140. int
  141. objc_alignof_type(const char* type)
  142. {
  143.   switch(*type) {
  144.   case _C_ID:
  145.     return __alignof__(id);
  146.     break;
  147.  
  148.   case _C_CLASS:
  149.     return __alignof__(OCClass*);
  150.     break;
  151.     
  152.   case _C_SEL:
  153.     return __alignof__(SEL);
  154.     break;
  155.  
  156.   case _C_CHR:
  157.     return __alignof__(char);
  158.     break;
  159.     
  160.   case _C_UCHR:
  161.     return __alignof__(unsigned char);
  162.     break;
  163.  
  164.   case _C_SHT:
  165.     return __alignof__(short);
  166.     break;
  167.  
  168.   case _C_USHT:
  169.     return __alignof__(unsigned short);
  170.     break;
  171.  
  172.   case _C_INT:
  173.     return __alignof__(int);
  174.     break;
  175.  
  176.   case _C_UINT:
  177.     return __alignof__(unsigned int);
  178.     break;
  179.  
  180.   case _C_LNG:
  181.     return __alignof__(long);
  182.     break;
  183.  
  184.   case _C_ULNG:
  185.     return __alignof__(unsigned long);
  186.     break;
  187.  
  188.   case _C_ATOM:
  189.   case _C_CHARPTR:
  190.     return __alignof__(char*);
  191.     break;
  192.  
  193.   case _C_ARY_B:
  194.     while (isdigit(*++type)) /* do nothing */;
  195.     return objc_alignof_type (type);
  196.       
  197.   case _C_STRUCT_B:
  198.     {
  199.       struct { int x; double y; } fooalign;
  200.       while(*type != _C_STRUCT_E && *type++ != '=') /* do nothing */;
  201.       if (*type != _C_STRUCT_E)
  202.     return MAX (objc_alignof_type (type), __alignof__ (fooalign));
  203.       else
  204.     return __alignof__ (fooalign);
  205.     }
  206.  
  207.   case _C_UNION_B:
  208.     {
  209.       int maxalign = 0;
  210.       while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
  211.       while (*type != _C_UNION_E)
  212.     {
  213.       maxalign = MAX (maxalign, objc_alignof_type (type));
  214.       type = objc_skip_typespec (type);
  215.     }
  216.       return maxalign;
  217.     }
  218.     
  219.   default:
  220.     abort();
  221.   }
  222. }
  223.  
  224. /*
  225.   The aligned size if the size rounded up to the nearest alignment.
  226. */
  227.  
  228. int
  229. objc_aligned_size (const char* type)
  230. {
  231.   int size = objc_sizeof_type (type);
  232.   int align = objc_alignof_type (type);
  233.  
  234.   if ((size % align) != 0)
  235.     return size + align - (size % align);
  236.   else
  237.     return size;
  238. }
  239.  
  240. /*
  241.   The size rounded up to the nearest integral of the wordsize, taken
  242.   to be the size of a void*.
  243. */
  244.  
  245. int 
  246. objc_promoted_size (const char* type)
  247. {
  248.   int size = objc_sizeof_type (type);
  249.   int wordsize = sizeof (void*);
  250.  
  251.   if ((size % wordsize) != 0)
  252.     return size + wordsize - (size % wordsize);
  253.   else
  254.     return size;
  255. }
  256.  
  257. /*
  258.   Skip type qualifiers.  These may eventually precede typespecs
  259.   occuring in method prototype encodings.
  260. */
  261.  
  262. inline const char*
  263. objc_skip_type_qualifiers (const char* type)
  264. {
  265.   while (*type == _C_CONST
  266.      || *type == _C_IN 
  267.      || *type == _C_INOUT
  268.      || *type == _C_OUT 
  269.      || *type == _C_BYCOPY
  270.      || *type == _C_ONEWAY)
  271.     {
  272.       type += 1;
  273.     }
  274.   return type;
  275. }
  276.  
  277.   
  278. /*
  279.   Skip one typespec element.  If the typespec is prepended by type
  280.   qualifiers, these are skipped as well.
  281. */
  282.  
  283. const char* 
  284. objc_skip_typespec (const char* type)
  285. {
  286.   type = objc_skip_type_qualifiers (type);
  287.   
  288.   switch (*type) {
  289.  
  290.   case _C_ID:
  291.     /* An id may be annotated by the actual type if it is known
  292.        with the @"ClassName" syntax */
  293.  
  294.     if (*++type != '"')
  295.       return type;
  296.     else
  297.       {
  298.     while (*++type != '"') /* do nothing */;
  299.     return type + 1;
  300.       }
  301.  
  302.     /* The following are one character type codes */
  303.   case _C_CLASS:
  304.   case _C_SEL:
  305.   case _C_CHR:
  306.   case _C_UCHR:
  307.   case _C_CHARPTR:
  308.   case _C_ATOM:
  309.   case _C_SHT:
  310.   case _C_USHT:
  311.   case _C_INT:
  312.   case _C_UINT:
  313.   case _C_LNG:
  314.   case _C_ULNG:
  315.   case _C_FLT:
  316.   case _C_DBL:
  317.   case _C_VOID:
  318.     return ++type;
  319.     break;
  320.  
  321.   case _C_ARY_B:
  322.     /* skip digits, typespec and closing ']' */
  323.     
  324.     while(isdigit(*++type));
  325.     type = objc_skip_typespec(type);
  326.     if (*type == _C_ARY_E)
  327.       return ++type;
  328.     else
  329.       abort();
  330.  
  331.   case _C_STRUCT_B:
  332.     /* skip name, and elements until closing '}'  */
  333.     
  334.     while (*type != _C_STRUCT_E && *type++ != '=');
  335.     while (*type != _C_STRUCT_E) { type = objc_skip_typespec (type); }
  336.     return ++type;
  337.  
  338.   case _C_UNION_B:
  339.     /* skip name, and elements until closing ')'  */
  340.     
  341.     while (*type != _C_UNION_E && *type++ != '=');
  342.     while (*type != _C_UNION_E) { type = objc_skip_typespec (type); }
  343.     return ++type;
  344.  
  345.   case _C_PTR:
  346.     /* Just skip the following typespec */
  347.     
  348.     return objc_skip_typespec (++type);
  349.     
  350.   default:
  351.     abort();
  352.   }
  353. }
  354.  
  355. /*
  356.   Skip an offset as part of a method encoding.  This is prepended by a
  357.   '+' if the argument is passed in registers.
  358. */
  359. inline const char* 
  360. objc_skip_offset (const char* type)
  361. {
  362.   if (*type == '+') type++;
  363.   while(isdigit(*++type));
  364.   return type;
  365. }
  366.  
  367. /*
  368.   Skip an argument specification of a method encoding.
  369. */
  370. const char*
  371. objc_skip_argspec (const char* type)
  372. {
  373.   type = objc_skip_typespec (type);
  374.   type = objc_skip_offset (type);
  375.   return type;
  376. }
  377.  
  378. /*
  379.   Return the number of arguments that the method MTH expects.
  380.   Note that all methods need two implicit arguments `self' and
  381.   `_cmd'. 
  382. */
  383. int
  384. method_get_number_of_arguments (struct objc_method* mth)
  385. {
  386.   int i = 0;
  387.   const char* type = mth->method_types;
  388.   while (*type)
  389.     {
  390.       type = objc_skip_argspec (type);
  391.       i += 1;
  392.     }
  393.   return i - 1;
  394. }
  395.  
  396. /*
  397.   Return the size of the argument block needed on the stack to invoke
  398.   the method MTH.  This may be zero, if all arguments are passed in
  399.   registers.
  400. */
  401.  
  402. int method_get_sizeof_arguments (struct objc_method* mth)
  403. {
  404.   const char* type = objc_skip_typespec (mth->method_types);
  405.   return atoi (type);
  406. }
  407.  
  408. /*
  409.   Return a pointer to the next argument of ARGFRAME.  type points to
  410.   the last argument.  Typical use of this look like:
  411.  
  412.   {
  413.     char *datum, *type; 
  414.     for (datum = method_get_first_argument (method, argframe, &type);
  415.          datum; datum = method_get_next_argument (argframe, &type))
  416.       {
  417.         unsigned flags = objc_get_type_qualifiers (type);
  418.         type = objc_skip_type_qualifiers (type);
  419.     if (*type != _C_PTR)
  420.           [portal encodeData: datum ofType: type];
  421.     else
  422.       {
  423.         if ((flags & _F_IN) == _F_IN)
  424.               [portal encodeData: *(char**)datum ofType: ++type];
  425.       }
  426.       }
  427.   }
  428. */  
  429.  
  430. char*
  431. method_get_next_argument (arglist_t argframe,
  432.               const char **type)
  433. {
  434.   const char *t = objc_skip_argspec (*type);
  435.  
  436.   if (*t == '\0')
  437.     return 0;
  438.  
  439.   *type = t;
  440.   t = objc_skip_typespec (t);
  441.  
  442.   if (*t == '+')
  443.     return argframe->arg_regs + atoi (++t);
  444.   else
  445.     return argframe->arg_ptr + atoi (t);
  446. }
  447.  
  448. /*
  449.   Return a pointer to the value of the first argument of the method 
  450.   described in M with the given argumentframe ARGFRAME.  The type
  451.   is returned in TYPE.  type must be passed to successive calls of 
  452.   method_get_next_argument.
  453. */
  454. char*
  455. method_get_first_argument (struct objc_method* m,
  456.                arglist_t argframe, 
  457.                const char** type)
  458. {
  459.   *type = m->method_types;
  460.   return method_get_next_argument (argframe, type);
  461. }
  462.  
  463. /*
  464.    Return a pointer to the ARGth argument of the method
  465.    M from the frame ARGFRAME.  The type of the argument
  466.    is returned in the value-result argument TYPE 
  467. */
  468.  
  469. char*
  470. method_get_nth_argument (struct objc_method* m,
  471.              arglist_t argframe, int arg, 
  472.              const char **type)
  473. {
  474.   const char* t = objc_skip_argspec (m->method_types);
  475.  
  476.   if (arg > method_get_number_of_arguments (m))
  477.     return 0;
  478.  
  479.   while (arg--)
  480.     t = objc_skip_argspec (t);
  481.   
  482.   *type = t;
  483.   t = objc_skip_typespec (t);
  484.  
  485.   if (*t == '+')
  486.     return argframe->arg_regs + atoi (++t);
  487.   else
  488.     return argframe->arg_ptr + atoi (t);
  489. }
  490.  
  491. unsigned
  492. objc_get_type_qualifiers (const char* type)
  493. {
  494.   unsigned res = 0;
  495.   BOOL flag = YES;
  496.  
  497.   while (flag)
  498.     switch (*type++)
  499.       {
  500.       case _C_CONST:  res |= _F_CONST; break;
  501.       case _C_IN:     res |= _F_IN; break;
  502.       case _C_INOUT:  res |= _F_INOUT; break;
  503.       case _C_OUT:    res |= _F_OUT; break;
  504.       case _C_BYCOPY: res |= _F_BYCOPY; break;
  505.       case _C_ONEWAY: res |= _F_ONEWAY; break;
  506.       default: flag = NO;
  507.     }
  508.  
  509.   return res;
  510. }
  511.